using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace TicTacToe
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        private enum GameStates
        {
            TitleScreen,
            ComputerFirst,
            Playing,
            Win,
            Loss,
            Draw
        } ;

        private GameStates gameState;
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        private Texture2D backGround;
        private Texture2D spriteSheet;
        private Texture2D win;
        private Texture2D loss;
        private Texture2D draw;
        private GameBoard gameBoard;
        private float timeSinceLastInput = 0.0f;
        private float minTimeBetweenInput = 0.15f;
        private bool playerFirst = true;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            graphics.PreferredBackBufferWidth = 250;
            graphics.PreferredBackBufferHeight = 250;
            graphics.ApplyChanges();

            gameState = GameStates.Playing;

            base.Initialize();
            
        }


        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
            backGround = Content.Load<Texture2D>(@"Textures\Background");
            spriteSheet = Content.Load<Texture2D>(@"Textures\SpriteSheet");
            win = Content.Load<Texture2D>(@"Textures\Win");
            loss = Content.Load<Texture2D>(@"Textures\Loss");
            draw = Content.Load<Texture2D>(@"Textures\Draw");
            gameBoard = new GameBoard(spriteSheet);

        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // TODO: Add your update logic here
            switch (gameState)
            {
                case GameStates.TitleScreen:
                    break;

                case GameStates.Playing:
                    timeSinceLastInput += (float)gameTime.ElapsedGameTime.TotalSeconds;
                    
                    if (timeSinceLastInput >= minTimeBetweenInput)
                    {
                        KeyboardState keyboardState = Keyboard.GetState();
                        if (keyboardState.IsKeyDown(Keys.Up))
                        {
                            gameBoard.MoveUp();
                            timeSinceLastInput = 0.0f;
                        }

                        else if (keyboardState.IsKeyDown(Keys.Down))
                        {
                            gameBoard.MoveDown();
                            timeSinceLastInput = 0.0f;
                        }

                        else if (keyboardState.IsKeyDown(Keys.Right))
                        {
                            gameBoard.MoveRight();
                            timeSinceLastInput = 0.0f;
                        }

                        else if (keyboardState.IsKeyDown(Keys.Left))
                        {
                            gameBoard.MoveLeft();
                            timeSinceLastInput = 0.0f;
                        }
                        else if (keyboardState.IsKeyDown(Keys.Space))
                        {
                            if (gameBoard.InsertPlayerPiece())
                            {
                                timeSinceLastInput = 0.0f;

                                if (GameBoard.CheckIfCrossWon(gameBoard._squares))
                                {
                                    gameState = GameStates.Win;
                                    return;
                                }
                                if (GameBoard.CheckIfCircleWon(gameBoard._squares))
                                {
                                    gameState = GameStates.Loss;
                                    return;
                                }
                                if (GameBoard.CheckForDraw(gameBoard._squares))
                                {
                                    gameState = GameStates.Draw;
                                    return;
                                }

                                gameBoard._squares = GameBoard.CalculateNextComputerMove(gameBoard._squares);

                                if (GameBoard.CheckIfCrossWon(gameBoard._squares))
                                {
                                    gameState = GameStates.Win;
                                    return;
                                }
                                if (GameBoard.CheckIfCircleWon(gameBoard._squares))
                                {
                                    gameState = GameStates.Loss;
                                    return;
                                }
                                if (GameBoard.CheckForDraw(gameBoard._squares))
                                {
                                    gameState = GameStates.Draw;
                                    return;
                                }
                            }


                        }
                    }
                    break;
                 case GameStates.Win:
                    Restart(gameTime);
                    break;
                case GameStates.Loss:
                    Restart(gameTime);
                    break;
                case GameStates.Draw:
                    Restart(gameTime);
                    break;
                default:
                    break;

            }

            base.Update(gameTime);
        }

        public void Restart(GameTime gameTime)
        {
            timeSinceLastInput += (float)gameTime.ElapsedGameTime.TotalSeconds;
            if (timeSinceLastInput >= minTimeBetweenInput)
            {
                KeyboardState keyboardState = Keyboard.GetState();
                if (keyboardState.IsKeyDown(Keys.Space))
                {
                    gameState = GameStates.Playing;
                    gameBoard.InitGameBoard();
                    timeSinceLastInput = 0.0f;
                }
            }
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here
            switch (gameState)
            {
                case GameStates.Playing:
                    spriteBatch.Begin();
                    spriteBatch.Draw(backGround, new Rectangle(0, 0, 250, 250), Color.White );
                    gameBoard.Draw(spriteBatch);
                    spriteBatch.End();
                    break;
                case GameStates.Win:
                    spriteBatch.Begin();
                    spriteBatch.Draw(win, new Rectangle(0, 0, 250, 250), Color.White);
                    gameBoard.Draw(spriteBatch);
                    spriteBatch.End();
                    break;
                case GameStates.Loss:
                    spriteBatch.Begin();
                    spriteBatch.Draw(loss, new Rectangle(0, 0, 250, 250), Color.White );
                    gameBoard.Draw(spriteBatch);
                    spriteBatch.End();
                    break;
                case GameStates.Draw:
                    spriteBatch.Begin();
                    spriteBatch.Draw(draw, new Rectangle(0, 0, 250, 250), Color.White);
                    gameBoard.Draw(spriteBatch);
                    spriteBatch.End();
                    break;

            }
            base.Draw(gameTime);
        }
    }
}
